#include "stdafx.h"
#include "JSGlobalFunction.h"
#include "mshtml.h"

#include "JSObj_Url.h"
#include "JSObj_KeyValue.h"
//#include "PtrDispatch.h"
#include "GlobalFunctionImpl.h"

void CreateFunDispInstance(IWebBrowser2* pBrowser, IDispatch** ppDisp, PGFINIT pInit)
{
	CZAFunctionDispatch* pExternal = new CZAFunctionDispatch(pBrowser, pInit);
	*ppDisp = pExternal;
	pExternal->AddRef();
}

_variant_t ExecuteScript(IWebBrowser2* pBrowser, LPCTSTR lpszFunName, IDispatch* pDispParam)
{
	_variant_t v;
	if (pDispParam)
		v = pDispParam;
	else
		v.vt = VT_EMPTY;
	return ExecuteScript(pBrowser, lpszFunName, v);
}

_variant_t ExecuteScript(IWebBrowser2* pBrowser, LPCTSTR lpszFunName, _variant_t& vParam)
{
	_variant_t vRet;
	try
	{
		if (pBrowser)
		{
			CComPtr<IDispatch> spDisp;
			pBrowser->get_Document(&spDisp);
			if (spDisp)
			{
				CComQIPtr<IHTMLDocument2> spDoc2(spDisp);
				spDisp.Release();
				
				if (spDoc2)
				{
#if 1
					CComBSTR bstr;
					spDoc2->get_URL(&bstr);
					CComQIPtr<IHTMLElement> spElemBody;
					spDoc2->get_body(&spElemBody);
					CComBSTR bstrHTML;
					spElemBody->get_innerHTML(&bstrHTML);
#endif
					spDoc2->get_Script(&spDisp);
					
					if (spDisp)
					{
						DISPPARAMS dispParam = {0};
						dispParam.rgvarg = &vParam;
						dispParam.cArgs = 1;
						
						DISPID dispID = 0;
						CComBSTR bstrFunName(lpszFunName);
						
						HRESULT hr = spDisp->GetIDsOfNames(IID_NULL, &bstrFunName, 1, LOCALE_SYSTEM_DEFAULT, &dispID);
						hr = spDisp->Invoke(dispID, IID_NULL, LOCALE_USER_DEFAULT,
							DISPATCH_METHOD, &dispParam, &vRet, 
							NULL, NULL);
// 						if (SUCCEEDED(hr))
// 							Debug_View(_T("SC: ExecuteScript suc\r\n"));
					}
				}
			}
//			Debug_View(_T("SC: ExecuteScript end\r\n"));
		}
	}
	catch (...)
	{
	}
	return vRet;
}

_variant_t EvalScript(IWebBrowser2* pBrowser, BSTR bstrCode, BSTR bstrLanguage)
{
	_variant_t vRet;
	try
	{
		if (pBrowser)
		{
			CComPtr<IDispatch> spDisp;
			pBrowser->get_Document(&spDisp);
			if (spDisp)
			{
				CComQIPtr<IHTMLDocument2> spDoc2(spDisp);
				spDisp.Release();
				
				if (spDoc2)
				{
					CComPtr<IHTMLWindow2> spWindow;
					spDoc2->get_parentWindow(&spWindow);
					
					if (spWindow)
					{
						_variant_t vRet = 0l;
						HRESULT hr = spWindow->execScript(bstrCode, bstrLanguage, &vRet);
						return vRet;
					}
				}
			}
		}
	}
	catch (...)
	{
	}
	return 0l;
}

_variant_t ExecuteDispatch( IDispatch* pFun, IDispatch* pParam )
{
	_variant_t vRet, vParam;
	try
	{
		vParam.vt = VT_DISPATCH; vParam.pdispVal = pParam;
		
		DISPPARAMS dispParam = {0};
		dispParam.cArgs = 1;
		dispParam.rgvarg = &vParam;
		
		pFun->Invoke(0, IID_NULL, LOCALE_USER_DEFAULT,
			DISPATCH_METHOD, &dispParam, &vRet, 
			NULL, NULL);
		
	}
	catch (...)
	{
	}

	vParam.vt = VT_EMPTY;
	return vRet;
}

CZAFunctionDispatch::CZAFunctionDispatch( IWebBrowser2* pBrowser, PGFINIT pInit ) : CFunctionDispatch(pBrowser)
{
	m_spFun = std::auto_ptr<I_GlobalFunction>(new CGlobalFunctionImpl);
	m_spFun->Init(pInit);
	SetParam(m_spFun.get());
	
	RegFun(_T("createSession"), JSGlobal_CreateSession);
	RegFun(_T("postUrl"), JSGlobal_PostUrl);
	RegFun(_T("getUrl"), JSGlobal_GetUrl);
	RegFun(_T("getGlobalValue"), JSGlobal_GetGlobalValue);
	RegFun(_T("setGlobalValue"), JSGlobal_SetGlobalValue);
	RegFun(_T("saveGlobalValue"), JSGlobal_SaveGlobalValue);
	RegFun(_T("addLog"), JSGlobal_AddLog);
}

_variant_t CZAFunctionDispatch::JSGlobal_CreateSession( IWebBrowser2* pBrowser, IDispatch* pDisp, void* pParam )
{
	I_GlobalFunction* p = (I_GlobalFunction*)pParam;
	IDispatch* pSession = NULL;
	HGFINTERNETSESSION hSession = p->CreateInternetSession();
	p->CreateDispatchAndAttachInternetSession(hSession, &pSession);
	if(pSession)
		return pSession;
	else
	{
		if (hSession)
			p->DestroyInternetSession(hSession);
		return 0l;
	}
}

_variant_t CZAFunctionDispatch::JSGlobal_PostUrl( IWebBrowser2* pBrowser, IDispatch* pDisp, void* pParam )
{
	I_GlobalFunction* p = (I_GlobalFunction*)pParam;

	CJSObj_Url url(pBrowser, pDisp);
	_variant_t vResult;

	GFOPENURL param = {0};
	param.nVerb = GFOPENURL_VERB_POST;
	param.hSession = p->GetInternetSessionFromDispatch(url.m_pSession);
	param.szUrl = url.m_bstrUrl;
	param.szHeader = url.m_bstrHeader;
	param.szData = url.m_bstrData;
	param.szRefer = url.m_bstrRefer;
	param.szResult.pfnAllocBuffer = GFSTRINGFUNCTION_variant_t::OnAllocBuffer;
	param.szResult.pfnReleaseBuffer = GFSTRINGFUNCTION_variant_t::OnReleaseBuffer;
	param.szResult.pfnSetString = GFSTRINGFUNCTION_variant_t::OnSetString;
	param.szResult.pContext = &vResult;
	param.nResultCodepage = url.m_lCodepage;

	if (p->OpenUrl(&param))
		return vResult;

	return 0l;
}

_variant_t CZAFunctionDispatch::JSGlobal_GetUrl( IWebBrowser2* pBrowser, IDispatch* pDisp, void* pParam )
{
	I_GlobalFunction* p = (I_GlobalFunction*)pParam;

	CJSObj_Url url(pBrowser, pDisp);
	_variant_t vResult;
	
	GFOPENURL param = {0};
	param.nVerb = GFOPENURL_VERB_GET;
	param.hSession = p->GetInternetSessionFromDispatch(url.m_pSession);
	param.szUrl = url.m_bstrUrl;
	param.szHeader = url.m_bstrHeader;
	param.szData = url.m_bstrData;
	param.szRefer = url.m_bstrData;
	param.szResult.pfnAllocBuffer = GFSTRINGFUNCTION_variant_t::OnAllocBuffer;
	param.szResult.pfnReleaseBuffer = GFSTRINGFUNCTION_variant_t::OnReleaseBuffer;
	param.szResult.pfnSetString = GFSTRINGFUNCTION_variant_t::OnSetString;
	param.szResult.pContext = &vResult;
	param.nResultCodepage = url.m_lCodepage;
	
	if (p->OpenUrl(&param))
		return vResult;
	
	return 0l;
}

_variant_t CZAFunctionDispatch::JSGlobal_GetGlobalValue( IWebBrowser2* pBrowser, IDispatch* pDisp, void* pParam )
{
	I_GlobalFunction* p = (I_GlobalFunction*)pParam;

	CJSObj_KeyValue kv(pBrowser, pDisp);
	GFSTRING szValue = {0};
	szValue.pfnAllocBuffer = GFSTRINGFUNCTION_bstr_t::OnAllocBuffer;
	szValue.pfnReleaseBuffer = GFSTRINGFUNCTION_bstr_t::OnReleaseBuffer;
	szValue.pfnSetString = GFSTRINGFUNCTION_bstr_t::OnSetString;
	szValue.pContext = &kv.m_bstrValue;

	VARIANT_BOOL vb = p->GetGlobalValue(kv.m_bstrKey, &szValue) ? VARIANT_TRUE : VARIANT_FALSE;
	if (VARIANT_FALSE!=vb)
		kv.SetAll();
	return vb;
}

_variant_t CZAFunctionDispatch::JSGlobal_SetGlobalValue( IWebBrowser2* pBrowser, IDispatch* pDisp, void* pParam )
{
	I_GlobalFunction* p = (I_GlobalFunction*)pParam;
	
	CJSObj_KeyValue kv(pBrowser, pDisp);
	p->SetGlobalValue(kv.m_bstrKey, kv.m_bstrValue);
	return 0l;
}

_variant_t CZAFunctionDispatch::JSGlobal_SaveGlobalValue( IWebBrowser2* pBrowser, IDispatch* pDisp, void* pParam )
{
	I_GlobalFunction* p = (I_GlobalFunction*)pParam;
	p->SaveGlobalValue();
	return 0l;
}

_variant_t CZAFunctionDispatch::JSGlobal_AddLog( IWebBrowser2* pBrowser, IDispatch* pDisp, void* pParam )
{
	I_GlobalFunction* p = (I_GlobalFunction*)pParam;

	CScriptObject so(pBrowser, pDisp);
	_bstr_t bstrValue;
	if (so.GetValue(_bstr_t("value"), &bstrValue))
		p->AddLog(bstrValue);

	return 0l;
}